/**
 * 两条互相垂直的线段AB和CD，分别等概率的选取一个点，求距离的期望
 * 显然就是 A + (B - A) * u 与 C + (D - C) * v 的距离的期望
 * 其中， u和v均在[0, 1]等概率选取，因此是一个双重积分
 * 使用辛普森计算，但是超时。
 * 题解是先旋转使得AB和CD为坐标轴，然后将双重积分化为r和theta的双重积分，
 * 然后进一步化为单重积分，最后可以使用定积分公式计算。  
 */
#include <bits/stdc++.h>
using namespace std;

#include <bits/extc++.h>
using namespace __gnu_pbds;

using Real = long double;
using llt = long long;
using ull = unsigned long long;
using pii = pair<int, int>;
using vi = vector<int>;
using vvi = vector<vi>;

#ifndef ONLINE_JUDGE
int const SZ = 34;
#else
int const SZ = 200000 + 12;
#endif

Real const EPS = 5E-11;
inline int sgn(Real x){return x >= EPS ? 1 : (x <= -EPS ? -1 : 0);}
inline bool is0(Real x){return 0 == sgn(x);}

struct SimpsonDoubleInt{

SimpsonDoubleInt() = delete;
SimpsonDoubleInt(function<Real(Real, Real)> func, Real epsi, const pair<Real, Real> & xRange, const pair<Real, Real> & yRange)
:f(func), eps(epsi), xrange(xRange), yrange(yRange), result(0.0)
{
    this->result = this->calc();
}

Real calc(){
    auto [x1, x2] = this->xrange;
    auto [y1, y2] = this->yrange;
    return this->asr(x1, x2, y1, y2, this->parabola(x1, x2, y1, y2));
}

/// 辛普森近似，就是抛物线近似
Real parabola(Real x1, Real x2, Real y) {
    auto mid = (x1 + x2) * 0.5;
    return (x2 - x1) * (this->f(x1, y) + this->f(x2, y) + 4.0 * this->f(mid, y)) / 6.0;    
}

/// 递归调用
Real asr(Real x1, Real x2, Real y, Real ans) {
    auto mid = (x1 + x2) * 0.5;
    auto lans = this->parabola(x1, mid, y);
    auto rans = this->parabola(mid, x2, y);
    if(fabs(lans + rans - ans) <= this->eps) return ans;
    return this->asr(x1, mid, y, lans) + this->asr(mid, x2, y, rans);
}

Real fByY(Real x1, Real x2, Real y) {
    return this->asr(x1, x2, y, this->parabola(x1, x2, y));
}

Real parabola(Real x1, Real x2, Real y1, Real y2) {
    auto mid = (y1 + y2) * 0.5;
    return (y2 - y1) * (this->fByY(x1, x2, y1) + this->fByY(x1, x2, y2) + 4.0 * this->fByY(x1, x2, mid)) / 6.0;
}

Real asr(Real x1, Real x2, Real y1, Real y2, Real ans) {
    auto mid = (y1 + y2) * 0.5;
    auto lans = this->parabola(x1, x2, y1, mid);
    auto rans = this->parabola(x1, x2, mid, y2);
    if(fabs(lans + rans - ans) <= this->eps) return ans;
    return this->asr(x1, x2, y1, mid, lans) + this->asr(x1, x2, mid, y2, rans);
}

Real getResult() const {return this->result;}

private:
function<Real(Real, Real)> f;
Real const eps;
pair<Real, Real> const xrange;
pair<Real, Real> const yrange;
Real result;

};

struct Point{
    Real x, y;
    
    Point(Real u=0,Real v=0):x(u),y(v){}

    Real cross(const Point & r) const {
        return this->x * r.y - r.x * this->y;
    }

    Real dot(const Point & r) const {
        return this->x * r.x + this->y * r.y;
    }

    Point & operator -= (const Point & r){
        this->x -= r.x;
        this->y -= r.y;
        return *this;
    }

    const Point operator - (const Point & r) const {
        return {this->x - r.x, this->y - r.y};
    }

    bool is0() const {
        return ::is0(this->x) and ::is0(this->y);
    }
};

Real cross(const Point & O, const Point & A, const Point & B){
    auto xoa = A.x - O.x, yoa = A.y - O.y;
    auto xob = B.x - O.x, yob = B.y - O.y;
    return xoa * yob - xob * yoa;
}

Point A, B, C, D;

inline Point rotate(const Point & p, Real cosValue, Real sinValue){
    return {
        cosValue * p.x - sinValue * p.y,
        sinValue * p.x + cosValue * p.y
    };
}

void transformBy(Point & o, Point & another, Point & u, Point & v){
    another -= o;
    u -= o;
    v -= o;
    o = {0., 0.};

    Real theta = atan2(another.y, another.x);
    theta = - theta;

    Real cosTheta = cos(theta);
    Real sinTheta = sin(theta);

    another = rotate(another, cosTheta, sinTheta);
    u = rotate(u, cosTheta, sinTheta);
    v = rotate(v, cosTheta, sinTheta);

    return;
}

void transform(Point & A, Point & B, Point & C, Point & D){
    auto tmp = sgn((B - A).cross(D - C));
    assert(tmp);

    if(tmp < 0){
        swap(A, C);
        swap(B, D);
    }

    transformBy(A, B, C, D);
    assert(A.is0());
    assert(is0(B.y) and sgn(B.x) > 0);
    assert(is0(C.x - D.x));
    assert(sgn(D.y - C.y) > 0);

    return;
}

Real proc(){
    // assert(is0((B - A).dot(D - C)));
    // transform(A, B, C, D);
    // auto ans = SimpsonDoubleInt(
    //     [&](Real x, Real y){return sqrt((x - C.x) * (x - C.x) + y * y);},
    //     EPS,
    //     {0, B.x},
    //     {C.y, D.y}
    // ).getResult();
    auto ans = SimpsonDoubleInt(
        [&](Real u, Real v)->Real{
            auto x1 = A.x + (B.x - A.x) * u;
            auto y1 = A.y + (B.y - A.y) * u;
            auto x2 = C.x + (D.x - C.x) * v;
            auto y2 = C.y + (D.y - C.y) * v;
            auto x = x1 - x2, y = y1 - y2;
            return sqrt(x * x + y * y);
        },
        EPS,
        {0., 1.},
        {0., 1.}
    ).getResult();
    return ans;
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("z.txt", "r", stdin);
#endif
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    int nofkase; cin >> nofkase;
    while(nofkase--){
        cin >> A.x >> A.y >> B.x >> B.y >> C.x >> C.y >> D.x >> D.y;
        cout << fixed << setprecision(23) << proc() << endl;
    }
    return 0;
}
